{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<font color=\"red\">注</font>: 使用 tensorboard 可视化需要安装 tensorflow (TensorBoard依赖于tensorflow库，可以任意安装tensorflow的gpu/cpu版本)\n",
    "\n",
    "```shell\n",
    "pip install tensorflow-cpu\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-29T02:50:08.125203900Z",
     "start_time": "2024-04-29T02:49:56.553689Z"
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:09:47.904853Z",
     "iopub.status.busy": "2025-02-02T14:09:47.904377Z",
     "iopub.status.idle": "2025-02-02T14:09:51.120754Z",
     "shell.execute_reply": "2025-02-02T14:09:51.119998Z",
     "shell.execute_reply.started": "2025-02-02T14:09:47.904819Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
      "  from .autonotebook import tqdm as notebook_tqdm\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=10, micro=14, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.0\n",
      "numpy 1.26.4\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.0\n",
      "torch 2.5.1+cu124\n",
      "cuda:0\n"
     ]
    }
   ],
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数据准备\n",
    "\n",
    "https://www.kaggle.com/competitions/cifar-10/data\n",
    "\n",
    "```shell\n",
    "$ tree -L 1 cifar-10                                    \n",
    "cifar-10\n",
    "├── sampleSubmission.csv\n",
    "├── test\n",
    "├── train\n",
    "└── trainLabels.csv\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-01-21T06:46:01.391389Z",
     "iopub.status.busy": "2025-01-21T06:46:01.390831Z",
     "iopub.status.idle": "2025-01-21T06:46:01.393562Z",
     "shell.execute_reply": "2025-01-21T06:46:01.393101Z",
     "shell.execute_reply.started": "2025-01-21T06:46:01.391365Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# %pip install py7zr\n",
    "# import py7zr\n",
    "# a = py7zr.SevenZipFile(r'../input/cifar-10/train.7z','r')\n",
    "# a.extractall(path=r'./')\n",
    "# a.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-21T06:46:01.394307Z",
     "iopub.status.busy": "2025-01-21T06:46:01.394134Z",
     "iopub.status.idle": "2025-01-21T06:46:01.511635Z",
     "shell.execute_reply": "2025-01-21T06:46:01.511010Z",
     "shell.execute_reply.started": "2025-01-21T06:46:01.394289Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "04_10_monkeys_model_1_aliyun.ipynb\t\t       runs\n",
      "05_10_monkeys_model_2_resnet50_finetune_2aliyun.ipynb  sampleSubmission.csv\n",
      "06_cifar10_model_2.ipynb\t\t\t       submission.csv\n",
      "checkpoints\t\t\t\t\t       test.7z\n",
      "competitions\t\t\t\t\t       train.7z\n",
      "kaggle.json\t\t\t\t\t       trainLabels.csv\n",
      "new-vgg-aliyun.ipynb\n"
     ]
    }
   ],
   "source": [
    "#我们不运行test数据集，太多图片\n",
    "!ls ."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-02-02T14:09:56.064007Z",
     "iopub.status.busy": "2025-02-02T14:09:56.063367Z",
     "iopub.status.idle": "2025-02-02T14:09:56.196305Z",
     "shell.execute_reply": "2025-02-02T14:09:56.195030Z",
     "shell.execute_reply.started": "2025-02-02T14:09:56.063948Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "!mkdir test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-29T02:50:17.556866200Z",
     "start_time": "2024-04-29T02:50:13.332056200Z"
    },
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:10:02.006540Z",
     "iopub.status.busy": "2025-02-02T14:10:02.006007Z",
     "iopub.status.idle": "2025-02-02T14:10:05.175116Z",
     "shell.execute_reply": "2025-02-02T14:10:05.174313Z",
     "shell.execute_reply.started": "2025-02-02T14:10:02.006496Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[(PosixPath('competitions/cifar-10/train/1.png'), 'frog'),\n",
      " (PosixPath('competitions/cifar-10/train/2.png'), 'truck'),\n",
      " (PosixPath('competitions/cifar-10/train/3.png'), 'truck'),\n",
      " (PosixPath('competitions/cifar-10/train/4.png'), 'deer'),\n",
      " (PosixPath('competitions/cifar-10/train/5.png'), 'automobile')]\n",
      "[(PosixPath('competitions/cifar-10/test/1.png'), 'cat'),\n",
      " (PosixPath('competitions/cifar-10/test/2.png'), 'cat'),\n",
      " (PosixPath('competitions/cifar-10/test/3.png'), 'cat'),\n",
      " (PosixPath('competitions/cifar-10/test/4.png'), 'cat'),\n",
      " (PosixPath('competitions/cifar-10/test/5.png'), 'cat')]\n",
      "50000 300000\n"
     ]
    }
   ],
   "source": [
    "from pathlib import Path\n",
    "\n",
    "DATA_DIR = Path(\".\")\n",
    "DATA_DIR1 =Path(\"competitions/cifar-10/\")\n",
    "train_lables_file = DATA_DIR / \"trainLabels.csv\"\n",
    "test_csv_file = DATA_DIR / \"sampleSubmission.csv\" #测试集模板csv文件\n",
    "train_folder = DATA_DIR1 / \"train\"\n",
    "test_folder = DATA_DIR1 / \"test\"\n",
    "\n",
    "#所有的类别\n",
    "class_names = [\n",
    "    'airplane',\n",
    "    'automobile',\n",
    "    'bird',\n",
    "    'cat',\n",
    "    'deer',\n",
    "    'dog',\n",
    "    'frog',\n",
    "    'horse',\n",
    "    'ship',\n",
    "    'truck',\n",
    "]\n",
    "\n",
    "def parse_csv_file(filepath, folder):\n",
    "    \"\"\"Parses csv files into (filename(path), label) format\"\"\"\n",
    "    results = []\n",
    "    #读取所有行\n",
    "    with open(filepath, 'r') as f:\n",
    "#         lines = f.readlines()  为什么加[1:]，可以试这个\n",
    "        #第一行不需要，因为第一行是标签\n",
    "        lines = f.readlines()[1:] \n",
    "    for line in lines:#依次去取每一行\n",
    "        image_id, label_str = line.strip('\\n').split(',')\n",
    "        image_full_path = folder / f\"{image_id}.png\"\n",
    "        results.append((image_full_path, label_str)) #得到对应图片的路径和分类\n",
    "    return results\n",
    "\n",
    "#解析对应的文件夹\n",
    "train_labels_info = parse_csv_file(train_lables_file, train_folder)\n",
    "test_csv_info = parse_csv_file(test_csv_file, test_folder)\n",
    "#打印\n",
    "import pprint\n",
    "pprint.pprint(train_labels_info[0:5])\n",
    "pprint.pprint(test_csv_info[0:5])\n",
    "print(len(train_labels_info), len(test_csv_info))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-29T02:50:22.471835700Z",
     "start_time": "2024-04-29T02:50:22.346907200Z"
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:10:05.176679Z",
     "iopub.status.busy": "2025-02-02T14:10:05.176329Z",
     "iopub.status.idle": "2025-02-02T14:10:05.272927Z",
     "shell.execute_reply": "2025-02-02T14:10:05.272173Z",
     "shell.execute_reply.started": "2025-02-02T14:10:05.176650Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                            filepath       class\n",
      "0  competitions/cifar-10/train/1.png        frog\n",
      "1  competitions/cifar-10/train/2.png       truck\n",
      "2  competitions/cifar-10/train/3.png       truck\n",
      "3  competitions/cifar-10/train/4.png        deer\n",
      "4  competitions/cifar-10/train/5.png  automobile\n",
      "                                filepath       class\n",
      "0  competitions/cifar-10/train/45001.png       horse\n",
      "1  competitions/cifar-10/train/45002.png  automobile\n",
      "2  competitions/cifar-10/train/45003.png        deer\n",
      "3  competitions/cifar-10/train/45004.png  automobile\n",
      "4  competitions/cifar-10/train/45005.png    airplane\n",
      "                           filepath class\n",
      "0  competitions/cifar-10/test/1.png   cat\n",
      "1  competitions/cifar-10/test/2.png   cat\n",
      "2  competitions/cifar-10/test/3.png   cat\n",
      "3  competitions/cifar-10/test/4.png   cat\n",
      "4  competitions/cifar-10/test/5.png   cat\n"
     ]
    }
   ],
   "source": [
    "# train_df = pd.DataFrame(train_labels_info)\n",
    "train_df = pd.DataFrame(train_labels_info[0:45000])\n",
    "valid_df = pd.DataFrame(train_labels_info[45000:])\n",
    "test_df = pd.DataFrame(test_csv_info)\n",
    "\n",
    "train_df.columns = ['filepath', 'class']\n",
    "valid_df.columns = ['filepath', 'class']\n",
    "test_df.columns = ['filepath', 'class']\n",
    "\n",
    "print(train_df.head())\n",
    "print(valid_df.head())\n",
    "print(test_df.head())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-29T02:50:31.586523100Z",
     "start_time": "2024-04-29T02:50:28.504142500Z"
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:10:06.451367Z",
     "iopub.status.busy": "2025-02-02T14:10:06.450846Z",
     "iopub.status.idle": "2025-02-02T14:10:07.580521Z",
     "shell.execute_reply": "2025-02-02T14:10:07.579701Z",
     "shell.execute_reply.started": "2025-02-02T14:10:06.451331Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from PIL import Image\n",
    "from torch.utils.data import Dataset, DataLoader\n",
    "from torchvision import transforms\n",
    "\n",
    "class Cifar10Dataset(Dataset):\n",
    "    df_map = {\n",
    "        \"train\": train_df,\n",
    "        \"eval\": valid_df,\n",
    "        \"test\": test_df\n",
    "    }\n",
    "    label_to_idx = {label: idx for idx, label in enumerate(class_names)}\n",
    "    idx_to_label = {idx: label for idx, label in enumerate(class_names)}\n",
    "    def __init__(self, mode, transform=None):\n",
    "        self.df = self.df_map.get(mode, None)\n",
    "        if self.df is None:\n",
    "            raise ValueError(\"mode should be one of train, val, test, but got {}\".format(mode))\n",
    "\n",
    "        self.transform = transform\n",
    "        \n",
    "    def __getitem__(self, index):\n",
    "        img_path, label = self.df.iloc[index]\n",
    "        img = Image.open(img_path).convert('RGB')\n",
    "        # # img 转换为 channel first\n",
    "        # img = img.transpose((2, 0, 1))\n",
    "        # transform\n",
    "        img = self.transform(img)\n",
    "        # label 转换为 idx\n",
    "        label = self.label_to_idx[label]\n",
    "        return img, label\n",
    "    \n",
    "    def __len__(self):\n",
    "        return self.df.shape[0]\n",
    "    \n",
    "IMAGE_SIZE = 32\n",
    "mean, std = [0.4914, 0.4822, 0.4465], [0.247, 0.243, 0.261]\n",
    "\n",
    "transforms_train = transforms.Compose([\n",
    "        # resize\n",
    "        transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n",
    "        # random rotation 40\n",
    "        transforms.RandomRotation(40),\n",
    "        # horizaontal flip\n",
    "        transforms.RandomHorizontalFlip(),\n",
    "        transforms.ToTensor(),\n",
    "        transforms.Normalize(mean, std)\n",
    "    ])\n",
    "\n",
    "transforms_eval = transforms.Compose([\n",
    "        # resize\n",
    "        transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n",
    "        transforms.ToTensor(),\n",
    "        transforms.Normalize(mean, std)\n",
    "    ])\n",
    "\n",
    "train_ds = Cifar10Dataset(\"train\", transforms_train)\n",
    "eval_ds = Cifar10Dataset(\"eval\", transforms_eval) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-29T02:51:31.864180800Z",
     "start_time": "2024-04-29T02:51:31.841167400Z"
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:10:07.582237Z",
     "iopub.status.busy": "2025-02-02T14:10:07.581748Z",
     "iopub.status.idle": "2025-02-02T14:10:07.586463Z",
     "shell.execute_reply": "2025-02-02T14:10:07.585751Z",
     "shell.execute_reply.started": "2025-02-02T14:10:07.582207Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "batch_size = 64\n",
    "train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=4)   \n",
    "eval_dl = DataLoader(eval_ds, batch_size=batch_size, shuffle=False, num_workers=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-05T09:51:19.396136500Z",
     "start_time": "2023-12-05T09:46:43.935044500Z"
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:10:10.394787Z",
     "iopub.status.busy": "2025-02-02T14:10:10.394294Z",
     "iopub.status.idle": "2025-02-02T14:10:10.398725Z",
     "shell.execute_reply": "2025-02-02T14:10:10.397929Z",
     "shell.execute_reply.started": "2025-02-02T14:10:10.394750Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
    "#这里不需要每次都执行，只需要执行一次就可以了，所以注释掉\n",
    "# def cal_mean_std(ds):\n",
    "#     mean = 0.\n",
    "#     std = 0.\n",
    "#     for img, _ in ds:\n",
    "#         mean += img.mean(dim=(1, 2))\n",
    "#         std += img.std(dim=(1, 2))\n",
    "#     mean /= len(ds)\n",
    "#     std /= len(ds)\n",
    "#     return mean, std\n",
    "#\n",
    "# # 经过 normalize 后 均值为0，方差为1\n",
    "# print(cal_mean_std(train_ds))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-29T02:52:55.126913100Z",
     "start_time": "2024-04-29T02:52:55.080936200Z"
    },
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:26:05.799135Z",
     "iopub.status.busy": "2025-02-02T14:26:05.798586Z",
     "iopub.status.idle": "2025-02-02T14:26:05.851288Z",
     "shell.execute_reply": "2025-02-02T14:26:05.850510Z",
     "shell.execute_reply.started": "2025-02-02T14:26:05.799089Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "             model.0.weight             paramerters num: 1728\n",
      "              model.0.bias              paramerters num: 64\n",
      "             model.3.weight             paramerters num: 73728\n",
      "              model.3.bias              paramerters num: 128\n",
      "             model.6.weight             paramerters num: 294912\n",
      "              model.6.bias              paramerters num: 256\n",
      "             model.8.weight             paramerters num: 589824\n",
      "              model.8.bias              paramerters num: 256\n",
      "            model.11.weight             paramerters num: 589824\n",
      "             model.11.bias              paramerters num: 256\n",
      "            model.13.weight             paramerters num: 589824\n",
      "             model.13.bias              paramerters num: 256\n",
      "            model.17.weight             paramerters num: 262144\n",
      "             model.17.bias              paramerters num: 256\n",
      "            model.18.weight             paramerters num: 2560\n",
      "             model.18.bias              paramerters num: 10\n"
     ]
    }
   ],
   "source": [
    "class VGG(nn.Module):\n",
    "    def __init__(self, num_classes):\n",
    "        super().__init__()\n",
    "        self.model = nn.Sequential(\n",
    "            nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, padding=\"same\"),# 64*32*32\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(kernel_size=2),\n",
    "            nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=\"same\"),# 128*16*16\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(kernel_size=2),\n",
    "            nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, padding=\"same\"),# 256*8*8\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, padding=\"same\"),# 256*8*8\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(kernel_size=2),\n",
    "            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, padding=\"same\"),# 256*4*4\n",
    "            nn.ReLU(),\n",
    "            nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, padding=\"same\"),# 256*4*4\n",
    "            nn.ReLU(),\n",
    "            nn.MaxPool2d(kernel_size=2), # 256*2*2\n",
    "            nn.Flatten(),\n",
    "            nn.Linear(1024,256),\n",
    "            nn.Linear(256, num_classes),\n",
    "        )\n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
    "        for m in self.modules():\n",
    "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
    "                nn.init.xavier_uniform_(m.weight)\n",
    "                nn.init.zeros_(m.bias)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        return self.model(x)\n",
    "        \n",
    "for key, value in VGG(len(class_names)).named_parameters():\n",
    "    print(f\"{key:^40}paramerters num: {np.prod(value.shape)}\")\n",
    "    \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-23T08:24:38.083191700Z",
     "start_time": "2024-07-23T08:24:38.072843500Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-02-02T14:10:13.770521Z",
     "iopub.status.busy": "2025-02-02T14:10:13.770040Z",
     "iopub.status.idle": "2025-02-02T14:10:13.775613Z",
     "shell.execute_reply": "2025-02-02T14:10:13.774812Z",
     "shell.execute_reply.started": "2025-02-02T14:10:13.770484Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "512"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "32*16"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-04-29T02:53:41.778122600Z",
     "start_time": "2024-04-29T02:53:41.736145400Z"
    },
    "collapsed": false,
    "execution": {
     "iopub.execute_input": "2025-02-02T14:10:14.240402Z",
     "iopub.status.busy": "2025-02-02T14:10:14.239900Z",
     "iopub.status.idle": "2025-02-02T14:10:14.248056Z",
     "shell.execute_reply": "2025-02-02T14:10:14.247307Z",
     "shell.execute_reply.started": "2025-02-02T14:10:14.240369Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total trainable parameters: 52266\n"
     ]
    }
   ],
   "source": [
    "#模型总参数量\n",
    "total_params = sum(p.numel() for p in VGG(len(class_names)).parameters() if p.requires_grad)\n",
    "print(f\"Total trainable parameters: {total_params}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-05T09:51:19.650361500Z",
     "start_time": "2023-12-05T09:51:19.432189700Z"
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:10:14.430267Z",
     "iopub.status.busy": "2025-02-02T14:10:14.429830Z",
     "iopub.status.idle": "2025-02-02T14:10:14.469619Z",
     "shell.execute_reply": "2025-02-02T14:10:14.468883Z",
     "shell.execute_reply.started": "2025-02-02T14:10:14.430236Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true,
    "tags": []
   },
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-05T09:51:26.334347900Z",
     "start_time": "2023-12-05T09:51:19.656342Z"
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:10:15.105993Z",
     "iopub.status.busy": "2025-02-02T14:10:15.105075Z",
     "iopub.status.idle": "2025-02-02T14:10:15.193301Z",
     "shell.execute_reply": "2025-02-02T14:10:15.192431Z",
     "shell.execute_reply.started": "2025-02-02T14:10:15.105936Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true,
    "tags": []
   },
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-05T09:51:26.347424300Z",
     "start_time": "2023-12-05T09:51:26.337347300Z"
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:10:20.473576Z",
     "iopub.status.busy": "2025-02-02T14:10:20.472911Z",
     "iopub.status.idle": "2025-02-02T14:10:20.480486Z",
     "shell.execute_reply": "2025-02-02T14:10:20.479770Z",
     "shell.execute_reply.started": "2025-02-02T14:10:20.473544Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true,
    "tags": []
   },
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-05T09:51:26.371402100Z",
     "start_time": "2023-12-05T09:51:26.351411800Z"
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:10:38.785927Z",
     "iopub.status.busy": "2025-02-02T14:10:38.785431Z",
     "iopub.status.idle": "2025-02-02T14:10:38.792188Z",
     "shell.execute_reply": "2025-02-02T14:10:38.791139Z",
     "shell.execute_reply.started": "2025-02-02T14:10:38.785892Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-12-05T09:51:26.364406400Z"
    },
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:26:09.589073Z",
     "iopub.status.busy": "2025-02-02T14:26:09.588582Z",
     "iopub.status.idle": "2025-02-02T14:28:01.406363Z",
     "shell.execute_reply": "2025-02-02T14:28:01.405008Z",
     "shell.execute_reply.started": "2025-02-02T14:26:09.589039Z"
    },
    "is_executing": true,
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 7040/7040 [01:51<00:00, 63.06it/s, epoch=9]\n"
     ]
    }
   ],
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits.argmax(axis=-1)\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 10\n",
    "\n",
    "model = VGG(num_classes=10)\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss()\n",
    "# 2. 定义优化器 采用 adam\n",
    "# Optimizers specified in the torch.optim package\n",
    "#可以修改adam里边的weight_decay参数，来控制L2正则化的程度,beta1和beta2是指数衰减率\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(\"runs/vgg\")\n",
    "tensorboard_callback.draw_model(model, [1, 3, IMAGE_SIZE, IMAGE_SIZE])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(\"checkpoints/vgg\", save_step=len(train_dl), save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=5)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model, \n",
    "    train_dl, \n",
    "    eval_dl, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=len(train_dl)\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-02-02T14:28:35.060426Z",
     "iopub.status.busy": "2025-02-02T14:28:35.059893Z",
     "iopub.status.idle": "2025-02-02T14:28:35.405021Z",
     "shell.execute_reply": "2025-02-02T14:28:35.404245Z",
     "shell.execute_reply.started": "2025-02-02T14:28:35.060384Z"
    },
    "is_executing": true,
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0QAAAHACAYAAACCp6jJAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzsnXeYVIXV/z/TZ2d7L4D0DqKiItiVohijJjEafW1JNImSXwwxJiSKokYSNWqK0fc1lpjExBRblCAIYgNBUVSQ3hbYXmd3Z3fq/f1x596Z2Sk7s33hfJ5nH5g79945U+7M/d5zzvcYFEVREARBEARBEARBOAYxDnQAgiAIgiAIgiAIA4UIIkEQBEEQBEEQjllEEAmCIAiCIAiCcMwigkgQBEEQBEEQhGMWEUSCIAiCIAiCIByziCASBEEQBEEQBOGYRQSRIAiCIAiCIAjHLCKIBEEQBEEQBEE4ZjEPdAC9QSAQoKKigszMTAwGw0CHIwiCcEyhKAotLS2UlZVhNMp1Ng35bRIEQRgYUv1dOioEUUVFBSNGjBjoMARBEI5pDh06xPDhwwc6jEGD/DYJgiAMLMn+Lh0VgigzMxNQn3RWVlbK23u9XlatWsX8+fOxWCy9HV6fIXH3L0Mx7qEYM0jc/U1P43Y6nYwYMUL/LhZU5LdJ4u5rhmLMIHH3N0Mx7v7+XToqBJFWipCVldXtHx2Hw0FWVtaQ+aCAxN3fDMW4h2LMIHH3N70Vt5SFRSK/TRJ3XzMUYwaJu78ZinH39++SFHsLgiAIgiAIgnDMIoJIEARBEARBEIRjFhFEgiAIgiAIgiAcsxwVPUSCIAxe/H4/Xq83pW28Xi9ms5mOjg78fn8fRdb7HK1xm0wmzGaz9Aj1AYqi4PP5Yr7uR+vnabCSatxyXAjC0YMIIkEQ+ozW1lYOHz6MoigpbacoCiUlJRw6dGhInWwczXE7HA5KS0uxWq39HN3Ri8fjobKyEpfLFfP+o/nzNBjpTtxyXAjC0YEIIkEQ+gS/38/hw4dxOBwUFhamdGIUCARobW0lIyNjSA36PBrjVhQFj8dDbW0t+/fvZ/z48UPquQ1WAoEA+/fvx2QyUVZWhtVqjTpGjsbP02AmlbjluBCEowsRRIIg9AlerxdFUSgsLCQtLS2lbQOBAB6PB7vdPqROMo7WuNPS0rBYLBw8eFBfT+gZHo+HQCDAiBEjcDgcMdc5Wj9Pg5VU45bjQhCOHobON5UgCEOSoVQyI8RnKJ3YDiXkdR3ayPsnCEcHKR3Jy5cv55RTTiEzM5OioiIuvfRSdu7cmXCbZ599FoPBEPHX+SqKoigsXbqU0tJS0tLSmDt3Lrt370792QiCIAiCIAiCIKRASoLo7bff5pZbbuGDDz5g9erVeL1e5s+fT1tbW8LtsrKyqKys1P8OHjwYcf8DDzzAb3/7W5544gk2btxIeno6CxYsoKOjI/VnJAiCIAiCIAiCkCQpCaKVK1dy/fXXM3XqVGbMmMGzzz5LeXk5mzdvTridwWCgpKRE/ysuLtbvUxSFRx99lDvuuINLLrmE448/nueee46Kigpefvnlbj0pQRCEwcCoUaN49NFHe2Vf69atw2Aw0NTU1Cv7E4TBQG8eI4IgCN2lR6YKzc3NAOTl5SVcr7W1lZEjRxIIBDjppJO4//77mTp1KgD79++nqqqKuXPn6utnZ2cza9YsNmzYwJVXXhm1P7fbjdvt1m87nU5AbeJOdd6Jtl34v0MFibt/GYpxD2TMmqlCIBAgEAiktK1m061t35+cd955zJgxg0ceeSTlbTvHrWW8e+M5aPvozuvZFcm83oFAAEVR8Hq9mEymiPuG0jEh9JxzzjmHE044oVeEzIcffkh6enrPgxIEQegB3RZEgUCAW2+9ldNPP51p06bFXW/ixIk8/fTTHH/88TQ3N/PQQw8xZ84ctm3bxvDhw6mqqgKIyBppt7X7OrN8+XKWLVsWtXzVqlVx3XqSYfXq1d3ediCRuPuXoRj3QMRsNpspKSmhtbUVj8fTrX20tLT0clRd4/P58Hg8+oWWziiKgt/vx2yO//WpxW2z2fD5fHH3lQrarJqWlpY+a+RO9Hp7PB7a29t555138Pl8MWMTBAgNm02GwsLCPo5GEAQhCZRu8t3vflcZOXKkcujQoZS283g8ytixY5U77rhDURRFef/99xVAqaioiFjv8ssvV77+9a/H3EdHR4fS3Nys/x06dEgBlLq6OsXj8aT85177K8W5fJLifu8P3dp+oP7a2tqUl19+WWlraxvwWCTuwfk3kDE7nU5l27ZtSltbm+L3+xWfz6e0tLuT+nO6OpSK6jrF6epIeptEfz6fT/H7/V3+XXvttQoQ8ffUU08pgPLaa68pJ510kmKxWJQ1a9You3btUi6++GKlqKhISU9PV04++WRl5cqVSmNjo/54I0eOVB5++GF9/4Dyv//7v8oll1yipKWlKePGjVNeeumlpGJbs2aNAij19fX6sn/84x/KlClTFKvVqowcOVJ58MEHI7b5/e9/r4wbN06x2WxKUVGR8pWvfEW/74UXXlCmTZum2O12JS8vTzn77LOV5ubmuI/f1tambNu2TXE6nVHvdV1dnQIozc3N3ftBOUppbm6O+7q0t7crX3zxhdLe3q4vCwQCSpvbq/+1tLuViuo6paXdHbG8t/8CgUDSz+m6666LOkaeeeYZBVBWrFihHyP/+c9/lF27dilf/vKXI46R1atXR+xv5MiRyiOPPKLfBpQnn3xSufTSS/Vj5JVXXkkqNp/Pp3zzm99URo0apdjtdmXChAnKo48+GrXeU089pR83JSUlyi233KIoiqL4/X7lwIEDyo033qgUFRUpNptNmTp1qvKf//wn7mPGeh/7E4/Ho7z88suKx+MZkMfvLhJ36vj9AWXpy58rD6zcnnC9/3t7r7Lo+Y8Vnz90XA/F17unMSf6/o1FtzJEixYt4rXXXuOdd95h+PDhKW1rsVg48cQT2bNnDwAlJSUAVFdXU1paqq9XXV3NCSecEHMfNpsNm80Wc98WiyWleAD8nhYyOyrwN+zC1I3tB5ruPu+BRuLuPwYiZr/fj8FgwGg0YjQacXl8TLt7YLJrX9yzAIfV1OV6v/3tb9m9ezfTpk3jnnvuAWDbtm0A/OxnP+Ohhx5izJgx5ObmcujQIS666CLuv/9+bDYbzz33HJdeeimbNm1i6tSpehZHew007r33Xh544AEeeughfve733HNNddw8ODBLkuPtX1or+fmzZu58sorufvuu7niiitYv349N998MwUFBVx//fV89NFH/OAHP+DPf/4zc+bMoaGhgXfffRej0UhlZSVXX301DzzwAJdddhnNzc16FjFe9sloNGIwGGJ+loba8TBYaff6mbL0jX5/XPX4SO504De/+Q27du2KeYz89Kc/5aGHHmLUqFGYzWaamppYuHAhv/jFL/Rj5OKLL2bnzp0cd9xxcR9j2bJlPPDAAzz44IP87ne/4+qrr07qGAkEAgwfPpx//vOf5Ofns379em666SZKS0v5+te/DsDjjz/O4sWL+eUvf8mFF15Ic3Mz77//vr795Zdfjsvl4i9/+Qtjx47liy++iCoRFYSB4B8fHeJPG1RTslvOHRf3mH1s3R6aXF5uOnMM04dn92eIQ5qUBJGiKHz/+9/npZdeYt26dYwePTrlB/T7/Xz++ecsXLgQgNGjR1NSUsKaNWt0AeR0Otm4cSPf+973Ut5/d1AKJgBgqBerb0E4lsnOzsZqteJwOPSLNTt27ADgnnvuYd68efq6eXl5zJgxQ79977338tJLL/Hf//5X75GMxfXXX883vvENAO6//35++9vfsmnTJi644IKUYn344Yc5//zzufPOOwGYMGECX3zxBQ8++CDXX3895eXlpKen86UvfYnMzExGjhzJiSeeCEBlZSU+n4+vfOUren/nyJEjycjISCkG4dgjmWMkEAjgdDojPnMQOkZeffVVFi1aFPcxunuMWCyWiHL60aNHs2HDBv7xj3/ogui+++7jRz/6ET/4wQ/09U455RQA3nzzTTZv3sy2bduYNGkSAGPGjEn6tRGEvqLZ5eWBN0Jjblo6fDEFkaIotHSo5ap1be6o+4X4pCSIbrnlFp5//nleeeUVMjMz9R6f7OxsfRL9tddey7Bhw1i+fDmgfkGedtppjBs3jqamJh588EEOHjzIt7/9bUC9enrrrbdy3333MX78eEaPHs2dd95JWVkZl156aS8+1QTkj1djqRNBJAh9RZrFxBf3LEhq3UAgQIuzhcyszF7pl0mz9PwK78knnxxxu7W1lbvvvpvXX39dFxjt7e0cPnw44X6OP/54/f/p6elkZWVRU1OTcjzbt2/nkksuiVh2+umn8+ijj+L3+5k3bx4jR45kzJgxXHDBBVxwwQVcdtllOBwOZsyYwfnnn8/06dNZsGABc+fOZcGCBWRlZaUcx1Discce48EHH6SqqooZM2bwu9/9jlNPPTXu+o8++iiPP/445eXlFBQU8LWvfY3ly5dHzdLrLTofI719HCR63N4g1jFyzz33RB0j5eXlCffTk2Pkscce4+mnn6a8vJz29nY8Ho9+sbWmpoaKigrOP//8mNt++umnlJWVMWHChKQeSxD6i4dX76ShLdSL29LhpTgr+nvI5fHjD6gmOfWt3evdPVZJSRA9/vjjgOowE84zzzzD9ddfD0B5eXnEF3djYyM33ngjVVVV5ObmMnPmTNavX8+UKVP0dW6//Xba2tq46aabaGpq4owzzmDlypV99qPTGSV/HACG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phF9iQiizqTnQ1oetDdA/W4ondH1NoIgdI3FoV6JToJAIICzpYWszEyMxl74srakdmHj6quv5sYbb+QPf/gDNpuNv/71r1x55ZUYjUZaW1u5++67ef3116msrMTn89He3k55eXmPw9y+fTszZszQxRDA6aefTiAQYOfOnZx11llcf/31LFiwgHnz5jF37ly+/vWvU1qqXklbvHgx3/72t/nzn//M3Llzufzyy3XhJAwBOh0jvX4cJHrcFOjq+Ljrrrt47bXXqK6u7vHx8eabb7J8+XJ27NiB0+nE5/PR0dGBy+XC4XCwZcsWLr/88pjbbt++HbfbrQs3QegPfvSPT6lv85BhM3HZid2rGnAmEESZcYazhmeI7BYTGTYzrW4f9a0ehmdbI9a9+9VtfHigkRyHhStOST1zmwqrv6jmkTd38fauGl68+fSY62g9Q+dMLOKp9/ZT7XSz6UBjn8bVGekhikWh5jQnZXOC0GsYDGpZTrJ/Fkdq6yf6S/Eq3cUXX4yiKLz++uscOnSId999l6uvvhqA2267jZdeeon777+fd999ly1btjB9+nQ8nv6p1X7mmWfYsGEDc+bM4YUXXmDChAl88MEHANx9991s27aNiy66iLVr1zJlyhReeumlfolL6AViHSO9eRz00/Hx8ssvc+edd/L222/36Pg4cOAAX/rSlzj++OP597//zebNm3nssccA9P2lpaXF3T7RfYLQF7h9fuqDfTvLV+zQXd9SJVGGKN5wVqeeIVIFk142F8Npble12of35va+79X59FATAOUN7THv7/D69fK/4iw7500qAuCtXXV9Hls4IohioTvNibGCIByL2O12vvKVr/DXv/6Vv/3tb0ycOJGTTjoJUBu4r7/+ei677DKmT59OSUkJBw4c6JXHnTx5Mp9++iltbW36svfffx+j0cjEiRP1ZSeeeCJLlixh/fr1TJs2jeeff16/b8KECfzwhz9k1apVfOUrX+GZZ57pldgEQaOr4+O6667jS1/6Uo+Pj82bNxMIBPj1r3/NaaedxoQJE6ioiMwyH3/88axZsybm9uPHjyctLS3u/YLQ24SbGNS0uPndmu5dWO9ZhkjdRiubq+9krNDY5tEF1/t76ujo49K0rRXqoNW6VnfMx6pxqoLNZjaSZTdz3qRiAN7aWZuK30uPEUEUC3GaE4RjnquvvprXX3+d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pk+fztatW3vssTds2MAVV1xBRkYGBoOBd9991+t+RVG49957SU9PJzw8nDlz5nD48GGvbcrKyrjuuuuIiYkhLi6OH/3oR9TU1Hhts2vXLi688ELCwsLIysri0Ucf7XDMy5Yt49xzzyU6OpqUlBSuvvpqDh486LVNQ0MDt99+O4mJiURFRfGtb32LwsJCr21yc3O5/PLLiYiIICUlhbvuuovGxkavbdavX88555yDzWZj2LBhrFixosNxP/vss0yYMEFf5GvGjBl8+OGHfTpmXx555BEMBgN33nlnn479/vvvx2AweH2MGjWqT8cMkJeXx/XXX09iYiLh4eGMHz+ebdu26ff3xb/J7OzsVs+1wWDg9ttvB/rucy38k2tTcOTa1Ht/v6FyXQK5Nsm1qQ1KP/f6668rVqtVWb58ubJ3717llltuUeLi4pTCwsIeefxVq1Ypv/nNb5S3335bAZR33nnH6/5HHnlEiY2NVd59911l586dypVXXqkMHjxYqa+v17e57LLLlIkTJypffPGF8tlnnynDhg1Trr32Wv3+yspKJTU1VbnuuuuUPXv2KK+99poSHh6u/P3vf+9QzPPnz1deeuklZc+ePcqOHTuUhQsXKgMHDlRqamr0bW699VYlKytLWbdunbJt2zblvPPOU84//3z9/sbGRmXcuHHKnDlzlK+//lpZtWqVkpSUpNxzzz36NseOHVMiIiKUpUuXKvv27VOefvppxWQyKatXr+5Q3P/73/+UlStXKocOHVIOHjyo/PrXv1YsFouyZ8+ePhtzS1u3blWys7OVCRMmKHfccYd+e1+M/b777lPGjh2r5Ofn6x/FxcV9OuaysjJl0KBByk033aRs2bJFOXbsmLJmzRrlyJEj+jZ98W+yqKjI63nOyclRAOWTTz5RFKVvPtfCP7k2BU+uTb3z9xtK1yVFkWuTXJt86/cJ0bRp05Tbb79d/97lcikZGRnKsmXLejyWlhcdt9utpKWlKY899ph+W0VFhWKz2ZTXXntNURRF2bdvnwIoX375pb7Nhx9+qBgMBiUvL09RFEX529/+psTHxyt2u13f5u6771ZGjhzZJXEXFRUpgPLpp5/qMVosFuU///mPvs3+/fsVQNm8ebOiKOrF1mg0KgUFBfo2zz77rBITE6PH+ctf/lIZO3as12MtWrRImT9/fpfErSiKEh8fr7zw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",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        # axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        # axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=100)  #横坐标是 steps"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecutionIndicator": {
     "show": true
    },
    "execution": {
     "iopub.execute_input": "2025-02-02T14:28:39.417092Z",
     "iopub.status.busy": "2025-02-02T14:28:39.416581Z",
     "iopub.status.idle": "2025-02-02T14:28:40.488090Z",
     "shell.execute_reply": "2025-02-02T14:28:40.486754Z",
     "shell.execute_reply.started": "2025-02-02T14:28:39.417056Z"
    },
    "is_executing": true,
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.8055\n",
      "accuracy: 0.7258\n"
     ]
    }
   ],
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(\"checkpoints/vgg/best.ckpt\", weights_only=True,  map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, eval_dl, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 推理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-21T06:47:22.291308Z",
     "iopub.status.busy": "2025-01-21T06:47:22.290944Z",
     "iopub.status.idle": "2025-01-21T06:47:22.293881Z",
     "shell.execute_reply": "2025-01-21T06:47:22.293440Z",
     "shell.execute_reply.started": "2025-01-21T06:47:22.291285Z"
    },
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# # test_df\n",
    "# test_ds = Cifar10Dataset(\"test\", transform=transforms_eval)\n",
    "# test_dl = DataLoader(test_ds, batch_size=batch_size, shuffle=False, drop_last=False)\n",
    "#\n",
    "# preds_collect = []\n",
    "# model.eval()\n",
    "# for data, fake_label in tqdm(test_dl):\n",
    "#     data = data.to(device=device)\n",
    "#     logits = model(data)\n",
    "#     preds = [test_ds.idx_to_label[idx] for idx in logits.argmax(axis=-1).cpu().tolist()]\n",
    "#     preds_collect.extend(preds)\n",
    "#\n",
    "# test_df[\"class\"] = preds_collect\n",
    "# test_df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-21T06:47:22.294784Z",
     "iopub.status.busy": "2025-01-21T06:47:22.294481Z",
     "iopub.status.idle": "2025-01-21T06:47:22.296790Z",
     "shell.execute_reply": "2025-01-21T06:47:22.296361Z",
     "shell.execute_reply.started": "2025-01-21T06:47:22.294764Z"
    },
    "is_executing": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "# # 导出 submission.csv\n",
    "# test_df.to_csv(\"submission.csv\", index=False)"
   ]
  }
 ],
 "metadata": {
  "kaggle": {
   "accelerator": "gpu",
   "dataSources": [
    {
     "databundleVersionId": 46718,
     "sourceId": 3649,
     "sourceType": "competition"
    }
   ],
   "dockerImageVersionId": 30588,
   "isGpuEnabled": true,
   "isInternetEnabled": true,
   "language": "python",
   "sourceType": "notebook"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
